package com.lin.service.impl;

import com.lin.service.AnalysisService;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.lang.Math;
@Service
public class AnalysisServiceImpl implements AnalysisService{


    public List<double[]> getHeatMap(double q, Double a) {
        int width = 250;
        int height = 200;
        double qBase = 100.0;
        List<double[]> data = new ArrayList<>();
        double x = 0.0;
        for (int i = 0; i < width; i++) {
            x += 0.1;
            double y = -1*a;
            for (int j = 0; j < height; j++) {
                y += 0.1;
                double mu = 1.0;
                double qy = getQy(x, "A");
                double qz = getQz(x, "A");
                double z = 1.0;
                double v = (qBase + q) / (2 * Math.PI * mu * qy * qz) * Math.exp(-0.5 * (y * y) / (qy * qy)) * 2 * (Math.exp(-0.5 * (z * z) / (qz * qz)));
                if (Double.isNaN(v)) {
                    v = 0;
                }
                double[] tmp = {i, j, v};
                data.add(tmp);
            }
        }
        x = -5.0;
        for (int i = 0; i < width; i++) {
            x += 0.1;
            double y = -1*a+5;
            for (int j = 0; j < height; j++) {
                y += 0.1;
                double mu = 1.0;
                double qy = getQy(x, "A");
                double qz = getQz(x, "A");
                double z = 1.0;
                double v = (qBase + q) / (2 * Math.PI * mu * qy * qz) * Math.exp(-0.5 * (y * y) / (qy * qy)) * 2 * (Math.exp(-0.5 * (z * z) / (qz * qz)));
                if (Double.isNaN(v)) {
                    v = 0;
                }
                data.get(i * height + j)[2] += v;
            }
        }
        x = -5.0;
        for (int i = 0; i < width; i++) {
            x += 0.1;
            double y = -15.0;
            for (int j = 0; j < height; j++) {
                y += 0.1;
                double mu = 1.0;
                double qy = getQy(x, "A");
                double qz = getQz(x, "A");
                double z = 1.0;
                double v = (qBase + q) / (2 * Math.PI * mu * qy * qz) * Math.exp(-0.5 * (y * y) / (qy * qy)) * 2 * (Math.exp(-0.5 * (z * z) / (qz * qz)));
                if (Double.isNaN(v)) {
                    v = 0;
                }
                data.get(i * height + j)[2] += v;
            }
        }

        for (int i = 0; i < data.size(); i++) {
            if (data.get(i)[2] <= 5) {
                data.remove(i);
                i--;
            }
        }
        for (int i = 0; i < data.size(); i++) {
            data.get(i)[0] /= 2;
            data.get(i)[1] /= 2;
            data.get(i)[0] += 75;
            data.get(i)[1] += 40;
        }
        return data;
    }

    public  List<double[]> getHeatMap3D(Double a) {
        List<double[]> dataList = new ArrayList<>();
        double x = 0.0;
        for (int i = 0; i < 30; i++) {
            x += 0.1;
            double y = a-10;
            for (int j = 0; j < 30; j++) {
                y += 0.1;
                double z = -1.5;
                for (int k = 0; k < 30; k++) {
                    z += 0.1;
                    double mu = 1.0;
                    double qy = getQy(x, "A");
                    double qz = getQz(x, "A");
                    double v = (100.0) / (2 * Math.PI * mu * qy * qz) * Math.exp(-0.5*(y*y)/(qy*qy)) * 2 * (Math.exp(-0.5 * (z * z) / (qz * qz)));
                    if (Double.isNaN(v)) {
                        v = 0;
                    }
                    double[] tmp = new double[]{i, j, k, v};
                    dataList.add(tmp);
                }
            }
        }
        x = 1.5;
        for (int i = 0; i < 30; i++) {
            x += 0.1;
            double y = a-5;
            for (int j = 0; j < 30; j++) {
                y += 0.1;
                double z = -2.0;
                for (int k = 0; k < 30; k++) {
                    z += 0.1;
                    double mu = 1.0;
                    double qy = getQy(x, "A");
                    double qz = getQz(x, "A");
                    double v = (100.0) / (2 * Math.PI * mu * qy * qz) * Math.exp(-0.5*(y*y)/(qy*qy)) * 2 * (Math.exp(-0.5 * (z * z) / (qz * qz)));
                    if (Double.isNaN(v)) {
                        v = 0;
                    }
                    dataList.get(i*900+j*30+k)[3] += v;
                }
            }
        }

        x = 1.5;
        for (int i = 0; i < 30; i++) {
            x += 0.1;
            double y = -3.0;
            for (int j = 0; j < 30; j++) {
                y += 0.1;
                double z = -1.0;
                for (int k = 0; k < 30; k++) {
                    z += 0.1;
                    double mu = 1.0;
                    double qy = getQy(x, "A");
                    double qz = getQz(x, "A");
                    double v = (100.0) / (2 * Math.PI * mu * qy * qz) * Math.exp(-0.5*(y*y)/(qy*qy)) * 2 * (Math.exp(-0.5 * (z * z) / (qz * qz)));
                    if (Double.isNaN(v)) {
                        v = 0;
                    }
                    dataList.get(i*900+j*30+k)[3] += v;
                }
            }
        }
        return dataList;
    }

    public static double getQy(double x, String q) {
        double a = 0.0;
        double r = 0.0;
        switch (q) {
            case "A":
                if (x <= 1000) {
                    a = 0.901074;
                    r = 0.425809;
                } else {
                    a = 0.850934;
                    r = 0.602052;
                }
                break;
            case "B":
                if (x <= 1000) {
                    a = 0.914370;
                    r = 0.281846;
                } else {
                    a = 0.865014;
                    r = 0.396353;
                }
                break;
            case "B-C":
                if (x <= 1000) {
                    a = 0.919325;
                    r = 0.229500;
                } else {
                    a = 0.875086;
                    r = 0.314238;
                }
                break;
            case "C":
                if (x <= 1000) {
                    a = 0.924279;
                    r = 0.177154;
                } else {
                    a = 0.885157;
                    r = 0.232123;
                }
                break;
            case "C-D":
                if (x <= 1000) {
                    a = 0.926849;
                    r = 0.143940;
                } else {
                    a = 0.886940;
                    r = 0.189396;
                }
                break;
            case "D":
                if (x <= 1000) {
                    a = 0.929418;
                    r = 0.110726;
                } else {
                    a = 0.888723;
                    r = 0.146669;
                }
                break;
            case "D-E":
                if (x <= 1000) {
                    a = 0.925118;
                    r = 0.0985631;
                } else {
                    a = 0.892794;
                    r = 0.124308;
                }
                break;
            case "E":
                if (x <= 1000) {
                    a = 0.920818;
                    r = 0.0864001;
                } else {
                    a = 0.896864;
                    r = 0.101947;
                }
                break;
            default:
                if (x <= 1000) {
                    a = 0.929418;
                    r = 0.0553634;
                } else {
                    a = 0.888723;
                    r = 0.0733348;
                }
                break;
        }
        return Math.pow(x, a) * r;
    }
    public static double getQz(double x, String Q) {
        double a = 0.0;
        double r = 0.0;
        switch (Q) {
            case "A":
                if (x <= 300) {
                    a = 1.12154;
                    r = 0.0799904;
                } else if (x > 300 && x <= 500) {
                    a = 1.51360;
                    r = 0.00854771;
                } else {
                    a = 2.10881;
                    r = 0.000211545;
                }
                break;
            case "B":
                if (x <= 500) {
                    a = 0.964435;
                    r = 0.127190;
                } else {
                    a = 0.109356;
                    r = 0.057025;
                }
                break;
            case "B-C":
                if (x <= 500) {
                    a = 0.941015;
                    r = 0.114682;
                } else {
                    a = 1.00770;
                    r = 0.0757182;
                }
                break;
            case "C":
                a = 0.917595;
                r = 0.106803;
                break;
            case "C-D":
                if (x <= 2000) {
                    a = 0.838628;
                    r = 0.126152;
                } else if (x > 2000 && x <= 10000) {
                    a = 0.756410;
                    r = 0.235667;
                } else {
                    a = 0.815575;
                    r = 0.136659;
                }
                break;
            case "D":
                if (x <= 1000) {
                    a = 0.826212;
                    r = 0.104634;
                } else if (x > 1000 && x <= 10000) {
                    a = 0.632023;
                    r = 0.400167;
                } else {
                    a = 0.55536;
                    r = 0.810763;
                }
                break;
            case "D-E":
                if (x <= 2000) {
                    a = 0.776864;
                    r = 0.111771;
                } else if (x > 2000 && x <= 10000) {
                    a = 0.572347;
                    r = 0.5289922;
                } else {
                    a = 0.499149;
                    r = 1.03810;
                }
                break;
            case "E":
                if (x <= 1000) {
                    a = 0.788370;
                    r = 0.0927529;
                } else if (x > 1000 && x <= 10000) {
                    a = 0.565188;
                    r = 0.433384;
                } else {
                    a = 0.414743;
                    r = 1.73241;
                }
                break;
            default:
                if (x <= 1000) {
                    a = 0.784400;
                    r = 0.0620765;
                } else if (x > 1000 && x <= 10000) {
                    a = 0.525969;
                    r = 0.370015;
                } else {
                    a = 0.322659;
                    r = 2.40691;
                }
                break;
        }
        return Math.pow(x, a) * r;
    }
}
